package studio.xiaoyun.common.tool;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.Collections;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.poi.hssf.converter.ExcelToHtmlConverter;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.xwpf.converter.core.BasicURIResolver;
import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

import studio.xiaoyun.common.convert.IHtmlConverter;
import studio.xiaoyun.core.exception.CoreException;
import studio.xiaoyun.core.exception.NotImplementedException;

/**
 * 使用POI作为转换器实现转换功能
 */
public class POITool implements IHtmlConverter{
    private static Logger log = LoggerFactory.getLogger(POITool.class);
    private List<String> supportedExtensionsForHtmlConverter;
    /**
     * 存放图片的路径
     */
    private final static String IMAGE_PATH = "image";

    @Override
    public void docToHtml(String sourceFileName, String targetFileName) {
        initFolder(targetFileName);
        String imagePathStr = initImageFolder(targetFileName);
        try {
            HWPFDocument wordDocument = new HWPFDocument(new FileInputStream(sourceFileName));
            WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
            //保存图片，并返回图片的相对路径
            wordToHtmlConverter.setPicturesManager((content, pictureType,name, width, height) -> {
            	FileOutputStream out = null;
                try{
                	out = new FileOutputStream(imagePathStr+name);
                	out.write(content);
                }catch(Exception exception){
                    log.error("保存图片出错",exception);
                }finally{
                    try {
                        out.close();
                    }catch(Exception e2){
                        log.error("关闭流出错",e2);
                    }
                }
                return IMAGE_PATH+"/"+name;
            });
            wordToHtmlConverter.processDocument(wordDocument);
            Document htmlDocument = wordToHtmlConverter.getDocument();
            DOMSource domSource = new DOMSource(htmlDocument);
            StreamResult streamResult = new StreamResult(new File(targetFileName));

            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.setOutputProperty(OutputKeys.METHOD, "html");
            serializer.transform(domSource, streamResult);
        } catch (Exception e) {
            log.error("将doc文件转换为html时出错", e);
            throw new CoreException("将doc文件转换为html时出错!" + e.getMessage());
        }
    }

    @Override
    public void docxToHtml(String sourceFileName, String targetFileName) {
        initFolder(targetFileName);
        String imagePathStr = initImageFolder(targetFileName);
        OutputStreamWriter outputStreamWriter = null;
        try {
            XWPFDocument document = new XWPFDocument(new FileInputStream(sourceFileName));
            XHTMLOptions options = XHTMLOptions.create();
            //存放图片的文件夹
            options.setExtractor( new FileImageExtractor( new File(imagePathStr ) ) );
            //html中图片的路径
            options.URIResolver( new BasicURIResolver(IMAGE_PATH));
            outputStreamWriter = new OutputStreamWriter(new FileOutputStream(targetFileName),"utf-8");
            XHTMLConverter xhtmlConverter = (XHTMLConverter)XHTMLConverter.getInstance();
            xhtmlConverter.convert(document, outputStreamWriter, options);
        } catch (Exception e) {
            log.error("将docx文件转换为html时出错", e);
            throw new CoreException("将docx文件转换为html时出错!" + e.getMessage());
        }finally{
            try{
                if(outputStreamWriter!=null){
                    outputStreamWriter.close();
                }
            }catch(Exception e){
                log.error("关闭文件流时出错", e);
            }
        }
    }

    @Override
    public void xlsToHtml(String sourceFileName, String targetFileName) {
        initFolder(targetFileName);
        try {
            Document doc = ExcelToHtmlConverter.process( new File( sourceFileName) );
            DOMSource domSource = new DOMSource( doc );
            StreamResult streamResult = new StreamResult( new File(targetFileName) );
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
            serializer.setOutputProperty( OutputKeys.INDENT, "yes" );
            serializer.setOutputProperty( OutputKeys.METHOD, "html" );
            serializer.transform( domSource, streamResult );
        }catch (Exception e) {
            log.error("将xls文件转换为html时出错", e);
            throw new CoreException("将xls文件转换为html时出错!" + e.getMessage());
        }
    }

    @Override
    public void xlsxToHtml(String sourceFileName, String targetFileName) {
        throw new NotImplementedException();
    }

    /**
     * 初始化存放html文件的文件夹
     * @param targetFileName html文件的文件名
     */
    private void initFolder (String targetFileName){
        File targetFile = new File(targetFileName);
        if (targetFile.exists()) {
            targetFile.delete();
        }
        String targetPathStr = targetFileName.substring(0, targetFileName.lastIndexOf(File.separator));
        File targetPath = new File(targetPathStr);
        //如果文件夹不存在，则创建
        if (!targetPath.exists()) {
            targetPath.mkdirs();
        }
    }

    /**
     * 初始化存放图片的文件夹
     * @param htmlFileName html文件的文件名
     * @return 存放图片的文件夹路径
     */
    private String initImageFolder(String htmlFileName){
        String targetPathStr = htmlFileName.substring(0, htmlFileName.lastIndexOf(File.separator));
        //创建存放图片的文件夹
        String imagePathStr = targetPathStr + File.separator + IMAGE_PATH+ File.separator;
        File imagePath = new File(imagePathStr);
        if (imagePath.exists()) {
            imagePath.delete();
        }
        imagePath.mkdir();
        return imagePathStr;
    }
    
    @Override
	public List<String> getSupportedExtensionsForHtmlConverter() {
		return supportedExtensionsForHtmlConverter==null?Collections.emptyList():supportedExtensionsForHtmlConverter;
	}

	@Override
	public void setSupportedExtensionsForHtmlConverter(List<String> supportedExtensionsForHtmlConverter) {
		this.supportedExtensionsForHtmlConverter = supportedExtensionsForHtmlConverter;
	}

}
